#pragma once
#include "EString.h"
#include "DriveStream.h"
#include "IVolumeParser.h"

namespace System
{
	typedef struct
	{
	/*
		80h = Bootable (Active Partition)
		00h = Non-bootable
	*/
		BYTE	bootCode;
	/*
		Starting Head (1 byte; 0h to FEh, for 255)
	*/
		BYTE	head;
	/*
			Starting Sector; only bits 0 thru 5; sector
			numbers always start with 1, so this gives
			us a max total of 63 sectors (01h to 3Fh).
			------------ ==========
	  
			Example: FA = 1111 1010, but only the first
			6 bits are used... xx11 1010 = 3Ah or 58.

			(Bits 6 and 7 are used as Bits 8 and 9 of the starting
			PartitionTable)
	*/
		BYTE	sector;
	/*
			Starting Cylinder; lower 8 bits (0 to 7)
			of this byte, plus bits 6 and 7 from the
			byte above to form a 10-bit number.
	*/
		BYTE	cylinder;
	/*
		system file type => 07 NTFS (thats what we are implementing in this)
		(the rest is just for information iven FAT)
	*/
		BYTE	type;
	/*
			"All versions of MS-DOS (including MS-DOS 7 [Windows 95])
			 have a bug which prevents booting on hard disks with 256
			 heads (FFh), so many modern BIOSes provide mappings with
			 at most 255 (FEh) heads."
	*/
		BYTE	endingHead;
	/*
		same as sector
	*/
		BYTE	endingSector;
	/*
		same as PartitionTable
	*/
		BYTE	endingCylinder;
	/*
		the name is good enought
	*/
		DWORD	firstPartitionSector;
		DWORD	numberOfSectors;
	}PARTITION;

	typedef enum
	{
		 PART_UNKNOWN			=	0x00 ,	//Unknown. 
		 PART_DOS2_FAT			=	0x01 ,	//12-bit FAT. 
		 PART_DOS3_FAT			=	0x04 ,	//16-bit FAT. Partition smaller than 32MB. 
		 PART_EXTENDED			=	0x05 ,	//Extended MS-DOS Partition. 
		 PART_DOS4_FAT			=	0x06 ,	//16-bit FAT. Partition larger than or equal to 32MB. 
		 PART_DOS32				=	0x0B ,	//32-bit FAT. Partition up to 2047GB. 
		 PART_DOS32X			=	0x0C ,	//Same as PART_DOS32(0Bh), but uses Logical Block Address Int 13h extensions. 
		 PART_DOSX13			=	0x0E,	//Same as PART_DOS4_FAT(06h), but uses Logical Block Address Int 13h extensions. 
		 PART_DOSX13X			=	0x0F ,	//Same as PART_EXTENDED(05h), but uses Logical Block Address Int 13h extensions. 
		 UNIX_PARTITION			=	0x63, 
		 LINUX_PARTITION		=	0x83,
		 LINUX_SWAP_PARTITION	=	0x82,
		 NTFS_PARTITION			=	0x07 ,	//NTFS-type partition! - most important for this										//it can also be HPFS
	}PartitionType;
	typedef enum
	{
		PART_TABLE			=		0,
		BOOT_RECORD			=		1,
		EXTENDED_PART		=		2,
	}PartitionPartType;

	typedef struct SYSTEM_API
	{
		StringList		path;
		String   fileSystem;
		String   deviceName;
		String   volumeName;
		String   userDefinedName;
		DWORD			serialNumber;
		DWORD			maxNameLen;	
		DWORD 			flags;
	}UDVolumeInformation;
	
	typedef struct SYSTEM_API 
	{
		DriveInfo				rawInfo;
		UDVolumeInformation		systemInfo;
	}PartitionInfo;

	typedef std::list<UDVolumeInformation>  VolumeList;
	typedef VolumeList::iterator			VolumeI;
	typedef VolumeList::const_iterator		VolumeCI;

	typedef std::list<PartitionInfo>					PartitionList;
	typedef std::list<PartitionInfo>::iterator			PartitionI;
	typedef std::list<PartitionInfo>::const_iterator	PartitionCI;

	typedef std::map<DWORD, IVolumeParser*>					VolumeParsersList;
	typedef std::map<DWORD, IVolumeParser*>::iterator			VolumeParsersI;
	typedef std::map<DWORD, IVolumeParser*>::const_iterator	VolumeParsersCI;

	class SYSTEM_API Volume
	{
	public:
		static VolumeList		getVolumes();
		static PartitionList	getAllPartitions(VolumeParsersList parsers);
	private:
		static StringList getPaths(LPCWSTR volumeName);
		static DriveList getPartitions(void);
	};
}